/* Webserver.java -- Matt Mahoney, mmahoney@cs.fit.edu

Webserver.java runs a simple web server.  To run, cd to the directory
containing the .html files to be served, and run:

  java Webserver >logfile

To kill the server, type Ctrl-C.

The server serves files only in the current directory and subdirectories.
It does not support CGI, cookies, authentication, keepalive, etc.
Client requests are logged to standard output.

Webserver accepts HTTP GET requests that begin with:

  GET /filename.html

If the file exists, it responds with:

  HTTP/1.0 200 OK\r\n
  Content-Type: text/html\r\n
  \r\n
  (contents of filename.html)

where \r\n is a carriage return and line feed.  The content type depends
on the filename extension as follows:

.html   text/html
.htm    text/html
.gif    image/gif
.jpeg   image/jpeg
.jpg    image/jpeg
.class  application/octet-stream
.*      text/plain  (all other extensions)

The server closes the connection after returning a file.  Keepalive
(the default in HTTP/1.1) is not implemented.

If the file does not exist or the request is not understood, the server
sends an HTTP "404 Not Found" error message back to the client.

If the client requests a directory without a trailing "/",
then the client is redirected to append it with an "HTTP 301 Moved
Permanently" response.  If the trailing slash is present, the server
returns the file index.html if it exists.

To prevent access outside the directory tree where the server was started,
file names containing "..", "|", or ":" are rejected.
*/

import java.util.*;
import java.io.*;
import java.net.*;
import net.sf.saxon.*;
import org.w3c.dom.*;
import javax.xml.parsers.*;
import javax.xml.xpath.*;
import java.lang.*;
import java.text.*;
import javax.xml.transform.*;
import javax.xml.namespace.*;

// A Webserver waits for clients to connect, then starts a separate
// thread to handle the request.
public class Webserver {
  private static ServerSocket serverSocket;
	

  public static void main(String[] args) throws IOException {
    serverSocket=new ServerSocket(8088);  // Start, listen on port 80
    while (true) {
      try {
        Socket s=serverSocket.accept();  // Wait for a client to connect
        new ClientHandler(s);  // Handle the client in a separate thread
      }
      catch (Exception x) {
        System.out.println(x);
      }
    }
  }
}

// A ClientHandler reads an HTTP request and responds
class ClientHandler extends Thread {
  private Socket socket;  // The accepted socket from the Webserver
	Transform xsltproc;

  // Start the thread in the constructor
  public ClientHandler(Socket s) {
    socket=s;
    start();
    xsltproc = new Transform();
  }
  
  public void handleOrder(String strOrder) {
  	try {
	  	File fileOrder = File.createTempFile("order", ".xml");
	  	saveFile(fileOrder, strOrder);
	  	DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
	  	Document docOrder = db.parse(fileOrder);
	  	NamedNodeMap atts = docOrder.getFirstChild().getAttributes();
	  	for (int i=0;i < atts.getLength(); i++)
	  		System.out.println(atts.item(i).getNodeName()+"-"+atts.item(i).getNodeValue());
	  	XPath xp = XPathFactory.newInstance().newXPath();
	  	NamespaceContext namespaceContext=new NamespaceContextImpl("cat", "urn:oasis:names:tc:ubl:CommonAggregateTypes:1.0:0.70");
			xp.setNamespaceContext(namespaceContext);
	  	String id= xp.evaluate("/Order/ID[1]", docOrder);
	  	System.out.println(id+" - " );
	  	fileOrder.renameTo(new File("server/order_"+id+".xml"));
	  } catch (Exception e) {
	  	System.out.println(e);
	  	e.printStackTrace();
	  }	
  }
  
  public boolean saveFile(File f, String contents){
		try {
			PrintWriter sfile = new PrintWriter(f);
			sfile.print(contents);
			sfile.close();
			return true;
		}
		catch (SecurityException se) {
			System.out.println("Caught a security exception");
			se.printStackTrace();
		}
		catch (IOException iox) {
			System.out.println("File save error...");
			iox.printStackTrace();
		}
		return false;
	}
  
  public String transform(String ebschema) {
    final StringWriter res = new StringWriter();
    final String febschema = ebschema;
  	try {
  		StandardURIResolver urir = new StandardURIResolver(new net.sf.saxon.Configuration());
  		TransformerFactoryImpl tfi = new TransformerFactoryImpl();
  		Source fxsl = (Source) urir.resolve("stylesheets/Message.xsl", "./");
	  	Controller xsl = (Controller) tfi.newTransformer(fxsl);
	  	Source xsd = (Source) xsltproc.loadDocuments(
	  	 febschema,
	  	 false, null, false);
	  	javax.xml.transform.stream.StreamResult resr = new javax.xml.transform.stream.StreamResult(res);
	  	xsl.transform(xsd, resr);
	  	
  	} catch (TransformerException e) {
  		System.out.println(e.getCause() );
  	  throw new Error(e);	
  	}

  	return res.toString();
  }

  // Read the HTTP request, respond, and close the connection
  public void run() {
    try {

      // Open connections to the socket
      BufferedReader in=new BufferedReader(new InputStreamReader(
        socket.getInputStream()));
      PrintStream out=new PrintStream(new BufferedOutputStream(
        socket.getOutputStream()));

      // Read filename from first input line "GET /filename.html ..."
      // or if not in this format, treat as a file not found.
      String s=in.readLine();
      System.out.println(s);  // Log the request
      String strOrder =  "";
      String bla;
			while (in.readLine().length() != 0) {}
			while (in.ready())
				strOrder += in.readLine();
			handleOrder(strOrder);
			
      // Attempt to serve the file.  Catch FileNotFoundException and
      // return an HTTP error "404 Not Found".  Treat invalid requests
      // the same way.
      String filename="";
      StringTokenizer st=new StringTokenizer(s);
      try {

        // Parse the filename from the GET command
        if (st.hasMoreElements() && st.nextToken().equalsIgnoreCase("GET")
            && st.hasMoreElements())
          filename=st.nextToken();
        else
          throw new FileNotFoundException();  // Bad request

        // Append trailing "/" with "index.html"
        if (filename.endsWith("/"))
          filename+="index.html";

        // Remove leading / from filename
        while (filename.indexOf("/")==0)
          filename=filename.substring(1);

        // Replace "/" with "\" in path for PC-based servers
        filename=filename.replace('/', File.separator.charAt(0));

        // Check for illegal characters to prevent access to superdirectories
        if (filename.indexOf("..")>=0 || filename.indexOf(':')>=0
            || filename.indexOf('|')>=0)
          throw new FileNotFoundException();

        // If a directory is requested and the trailing / is missing,
        // send the client an HTTP request to append it.  (This is
        // necessary for relative links to work correctly in the client).
        if (new File(filename).isDirectory()) {
          filename=filename.replace('\\', '/');
          out.print("HTTP/1.0 301 Moved Permanently\r\n"+
            "Location: /"+filename+"/\r\n\r\n");
          out.close();
          return;
        }

        // Open the file (may throw FileNotFoundException)
        InputStream f=new FileInputStream(filename);

        // Determine the MIME type and print HTTP header
        String mimeType="text/plain";
        if (filename.endsWith(".html") || filename.endsWith(".htm"))
          mimeType="text/html";
        else if (filename.endsWith(".jpg") || filename.endsWith(".jpeg"))
          mimeType="image/jpeg";
        else if (filename.endsWith(".gif"))
          mimeType="image/gif";
        else if (filename.endsWith(".class"))
          mimeType="application/octet-stream";
        out.print("HTTP/1.0 200 OK\r\n"+
          "Content-type: "+mimeType+"\r\n\r\n");

        // Send file contents to client, then close the connection
        byte[] a=new byte[4096];
        int n;
        while ((n=f.read(a))>0)
          out.write(a, 0, n);
        out.close();
      }
      catch (FileNotFoundException x) {
        out.println("HTTP/1.0 404 Not Found\r\n"+
          "Content-type: text/html\r\n\r\n"+
          "<html><head></head><body>"+filename+" not found</body></html>\n");
        out.close();
      }
    }
    catch (IOException x) {
      System.out.println(x);
    }
  }
  
  public class NamespaceContextImpl implements NamespaceContext{
 
		public String uri;
		public String prefix;
		
		public NamespaceContextImpl(){}
		
		public NamespaceContextImpl(String prefix, String uri){
		   this.uri=uri;
		   this.prefix=prefix;
		  }
		
		public String getNamespaceURI(String prefix){
		 return uri;
		}
		public void setNamespaceURI(String uri){
		 this.uri=uri;
		}
		
		public String getPrefix(String uri){
		 return prefix;
		}
		
		public void setPrefix(String prefix){
		 this.prefix=prefix;
		}
		public Iterator getPrefixes(String uri){return null;}
		
	}
}

